﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Swashbuckle.AspNetCore.Swagger;
using BCGPSCommon;
using AppSocketService;
using BCGPSRESTful.WebApiConfig;
using Microsoft.AspNetCore.Mvc;
using AppSocketModel;

namespace BCGPSRESTful
{
    /// <summary>
    /// 
    /// </summary>
    public class Startup
    {
        /// <summary>
        /// 构造函数 - 读取配置文件
        /// </summary>
        public Startup()
        {
            GeneralContainer.configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .Build();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="services"></param>
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            //这个必须加
            services.AddMvc().AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy { ProcessDictionaryKeys = false } };
                options.SerializerSettings.Converters.Add(new StringEnumConverter { AllowIntegerValues = true });
                options.SerializerSettings.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeLocal, DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
                options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
            });
            //自定义模型验证
            services.Configure<ApiBehaviorOptions>(s =>
            {
                s.InvalidModelStateResponseFactory = (context) =>
                {
                    if (context.ModelState.IsValid)
                        return null;
                    var errorMessageDto = new ErrorMessageDto();
                    foreach (var item in context.ModelState)
                    {
                        var state = item.Value;
                        var message = state.Errors.FirstOrDefault(p => !string.IsNullOrWhiteSpace(p.ErrorMessage))?.ErrorMessage;
                        if (string.IsNullOrWhiteSpace(message))
                        {
                            message = state.Errors.FirstOrDefault(o => o.Exception != null)?.Exception.Message;
                        }
                        if (string.IsNullOrWhiteSpace(message))
                            continue;
                        errorMessageDto.ErrorCode = "99996";
                        errorMessageDto.ErrorMessage = message;
                        break;
                    }

                    return new BadRequestObjectResult(errorMessageDto);
                };
            });
            // 允许跨域
            services.AddCors(options => options.AddPolicy("CorsUrl", p => p.WithOrigins("*").AllowAnyMethod().AllowAnyHeader()));

            services.AddSwaggerGen(s =>
            {
                s.SwaggerDoc("CompanyPage", new Info { Title = "企业账号 - 网页端", Version = "V2" }); 
                s.SwaggerDoc("PersonPage", new Info { Title = "个人用户 - 网页端", Version = "V2" });
                s.SwaggerDoc("CompanyApp", new Info { Title = "企业用户 - 手机端", Version = "V2" });
                s.SwaggerDoc("PersonApp", new Info { Title = "个人用户 - 手机端", Version = "V2" });
                s.SwaggerDoc("DeviceCmd", new Info { Title = "设备命令 - 网页端", Version = "V2" });
                s.SwaggerDoc("SystemAccount", new Info { Title = "系统账号 - 网页端", Version = "V2" });
                s.SwaggerDoc("Test", new Info { Title = "测试用", Version = "V2" });

                s.OperationFilter<AddAuthTokenHeaderParameter>();

                s.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "BCGPSRESTful.xml"));
                s.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "AppSocketModel.xml"));
                s.DocumentFilter<EnumDocumentFilter>();
            });

            services.AddHttpContextAccessor();

            services.AddService();          //用反射注册全部的类

            services.AddMapperConfiguration();
            // JWT 选项 
            services.AddAuthentication(s =>
            {
                s.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                s.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

            }).AddJwtBearer(s =>
           {
               s.TokenValidationParameters = new TokenValidationParameters
               {

                   ValidateIssuerSigningKey = true,
                   IssuerSigningKey = TokenExtension.SecurityKey,

                   ValidateIssuer = true,
                   ValidIssuer = TokenExtension.Issuer,

                   ValidateAudience = true,
                   ValidAudience = TokenExtension.Audience,

                   ValidateLifetime = true,
                   ClockSkew = TimeSpan.Zero

               };
           });
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name = "app" ></param >
        /// <param name="env"></param>
        // This method gets called by the runtime.Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseCors("CorsUrl");
            app.UseSwagger();

            app.UseSwaggerUI(s =>
            {
                s.RoutePrefix = string.Empty;

                var swagger = $@"{Directory.GetCurrentDirectory()}{Path.DirectorySeparatorChar}wwwroot{Path.DirectorySeparatorChar}swagger.template.html";

                if (File.Exists(swagger))
                {
                    s.IndexStream = () => new FileStream(swagger, FileMode.Open);
                }

                s.SwaggerEndpoint("/swagger/CompanyPage/swagger.json", "企业账号 - 网页端"); 
                s.SwaggerEndpoint("/swagger/PersonApp/swagger.json", "个人用户 - 手机端");
                s.SwaggerEndpoint("/swagger/DeviceCmd/swagger.json", "设备命令 - 网页端");
                s.SwaggerEndpoint("/swagger/SystemAccount/swagger.json", "系统账号 - 网页端");
                s.SwaggerEndpoint("/swagger/Test/swagger.json", "测试用");

                s.InjectStylesheet("/styles/swagger.css");
                s.InjectOnCompleteJavaScript("/scripts/swagger.js");
            });

            app.UseAuthentication();
            app.UseHttpsRedirection();
            app.UseMvc();
            app.UseStaticFiles();

            new ConfigurationManager();

            AppSocketService.GpsRedis.GpsRedis.ClearRedis();
            AppSocketService.GpsRedis.GpsRedis.InitCompanyAccountRedis();
            AppSocketService.GpsRedis.GpsRedis.InitPersonAccountRedis();
            AppSocketService.GpsRedis.GpsRedis.InitDeviceRedis();
            AppSocketService.GpsRedis.GpsRedis.InitAlarmCompanyRedis();
            AppSocketService.GpsRedis.GpsRedis.InitAlarmPersonRedis();
        }
    }
}